`ifndef NewLabel_MEMIF_AGENT_SV
`define NewLabel_MEMIF_AGENT_SV

import ovm_pkg::*;
`include "ovm_macros.svh"
import	definitions::*;

interface MemIf(input logic mclk, rst_n);

	wire logic [23:0]	data_m;
	logic [23:0]	data_wr;
	logic [25:0]	addr_m;
	logic cs_m;
	logic [2:0]	gpctrl_m;
	logic finish_s;
	int data_id;

	assign data_m = gpctrl_m[1]? data_wr : 'z;

 	/*modport drv(
		input mclk, rst_n,
		inout data, 
		output addr, cs, wr, wr_full_flag, rd_empty_flag
  	);*/
 	   
endinterface

////////////////////////// items /////////////////////////
/*class tr_memif extends ovm_sequence_item;
	rand logic[23:0] data;
	rand logic[4:0]	addr;
	rand Bus_OP_t op;
	rand int trans_delay;
	rand int data_id;
	rand bit last_data;

	constraint trans_delay_con{trans_delay>=0; trans_delay<=30;}

	`ovm_object_utils_begin(tr_memif)
		`ovm_field_int(data, OVM_ALL_ON + OVM_HEX)
		`ovm_field_int(addr, OVM_ALL_ON + OVM_HEX)
		`ovm_field_enum(Bus_OP_t, op, OVM_ALL_ON + OVM_HEX)
		`ovm_field_int(trans_delay, OVM_ALL_ON + OVM_HEX)
		`ovm_field_int(data_id, OVM_ALL_ON + OVM_HEX)
		`ovm_field_int(last_data, OVM_ALL_ON + OVM_HEX)
	`ovm_object_utils_end

	function new (string name = "tr_memif");
		super.new(name);
	endfunction : new

	virtual function void do_print(ovm_printer printer);
		super.do_print(printer);
	endfunction : do_print
	
endclass : tr_memif*/

////////////////////////// drivers /////////////////////////
class NewLabel_memif_driver extends ovm_driver;
	virtual MemIf if0;
	`ovm_component_utils(NewLabel_memif_driver)	
	int unsigned m_mem[int unsigned];
	int unsigned data_id;

	function new(string name, ovm_component parent);
		super.new(name, parent);
	endfunction : new

	function void assign_vi(virtual interface MemIf if0);
	  this.if0 = if0;     
	endfunction : assign_vi

	task run();
		init_signals();

		forever begin
		  //seq_item_port.get_next_item(req);
		  //$cast(rsp, req.clone());
		  //req.print();
			//ovm_report_info("TRP", $psprintf("Detail:\n%s", req.sprint()), OVM_FULL);

		  drive_transfer();
		        
		  //$cast(rsp, req.clone());
		  //rsp.set_id_info(req);
		  //seq_item_port.item_done(rsp);
		end
	endtask : run

	task init_signals();
		time run_delay;
		assert(get_config_int("run_delay", run_delay));
		#run_delay;
		wait(if0.rst_n);

	endtask : init_signals

	task drive_transfer();
		
		//ovm_report_info("memif write", "Driving...", OVM_HIGH);
	    //ovm_report_info("memif write", $psprintf("Detail:\n%s", trans.sprint()), OVM_FULL);
	    @(posedge if0.mclk iff if0.cs_m === 1'b1)
	    begin
	    	if(if0.gpctrl_m === 'h1)
	    	begin
	    		m_mem[if0.addr_m] = if0.data_m;
	    		data_id++;
	    	end
	    	else if(if0.gpctrl_m === 'h2)
	    	begin
	    		if0.data_wr = m_mem[if0.addr_m];
	    		data_id--;
	    	end
    		if0.data_id = data_id;
		end

	endtask : drive_transfer
	
endclass : NewLabel_memif_driver


////////////////////////// AGENT /////////////////////////
class NewLabel_memif_agent extends ovm_agent;
  ovm_active_passive_enum is_active = OVM_ACTIVE;
  
  `ovm_component_utils_begin(NewLabel_memif_agent)
    `ovm_field_enum(ovm_active_passive_enum, is_active, OVM_ALL_ON)
  `ovm_component_utils_end
  
  //NewLabel_memif_sequencer memif_seqr;
  NewLabel_memif_driver memif_driver;
  
  function new(string name, ovm_component parent=null);
    super.new(name, parent);
  endfunction
  
  virtual function void build();
    super.build();
    if (is_active == OVM_ACTIVE) 
    begin
      //memif_seqr = NewLabel_memif_sequencer::type_id::create("memif_seqr",this);
      memif_driver = NewLabel_memif_driver::type_id::create("memif_driver",this);
    end
  endfunction : build
  
  virtual function void connect();
    super.connect();
    if(is_active == OVM_ACTIVE) 
    begin
      //memif_driver.seq_item_port.connect(memif_seqr.seq_item_export);
    end
  endfunction : connect

  function void assign_vi(virtual interface MemIf bif);
  	if (is_active == OVM_ACTIVE)
  	begin
  		memif_driver.assign_vi(bif);
  	end
  endfunction : assign_vi
endclass : NewLabel_memif_agent


`endif // NewLabel_MEMIF_AGENT_SV

